---
title: MySQL主从同步
---
slave 会从 master 读取 binlog 来进行数据同步。


## 基本原理



![image-20230412224201727](https://img.wkq.pub/pic/image-20230412224201727.png)

1. master 将数据改变记录到二进制日志（binary log） 中。
2. 当 slave 上执行 `start slave` 命令后，slave 会创建一个 IO 线程用来连接 master，请求 master 中的 binlog。
3. 当 slave 连接上 master 时，master 会创建一个 `log dump` 线程，用于发送 binlog 的内容。在读取 binlog 的内容的操作中，会对主节点上的 binlog 加锁，当读取完成并发送给服务器后解锁。
4. IO 线程接收主节点 binlog dump 进程发来的更新之后，保存到中继日志（relay log） 中。
5. slave 的 SQL 线程，读取 relay log日志，并解析成具体操作，从而实现主从操作一致，最终数据一致。

## 一主多从配置

服务器规划：使用 docker 方式创建，主从服务器 IP 一致，端口号不一致

* 主服务器：容器名 `mysql-master`,端口 3306。
* 从服务器：容器名 `mysql-slave1`,端口 3307.
* 从服务器：容器名 `mysql-slave2`,端口 3308.



### 准备主服务器

1. 创建 MySQL 主服务器配置文件：my.cnf

   ```cnf
   [mysqld]
   # 服务器唯一id，默认值1
   server-id=1
   # 设置日志格式，默认值ROW
   binlog_format=STATEMENT
   # 二进制日志名，默认binlog
   # log-bin=binlog
   # 设置需要复制的数据库，默认复制全部数据库
   #binlog-do-db=mytestdb
   # 设置不需要复制的数据库
   #binlog-ignore-db=mysql
   #binlog-ignore-db=infomation_schema
   ```

2. 在 docker 中创建并启动 MySQL 主服务器。

    ```shell
    docker run -d \
    -p 3306:3306 \
    -v /root/mysql/master/conf:/etc/mysql/conf.d \
    -v /root/mysql/master/data:/var/lib/mysql \
    -e MYSQL_ROOT_PASSWORD=123456 \
    --name mysql-master \
    mysql
```



binlog 格式说明：

* binlog_format = STATEMENT: 日志记录的是数据库的写指令，性能高，但是 now() 之类的函数以及获取系统参数的操作会出现主从数据不同步的问题。
* binlog_format = ROW（默认）：日志记录的是主机数据库的写后的数据，批量操作时性能较差，解决 now() 或 user() 或者 @@hostname 等操作主从机器上不一致的问题。
* binglog_format = MIXED : 是以上两种 level 的混合使用，有函数用 ROW，没函数用 STATEMENT，但是无法标识系统变量。

binlog-ignore-db 和 binlog-do-db 的优先级问题：

![image-20230412232154507](https://img.wkq.pub/pic/image-20230412232154507.png)

3. 使用 命令行登录 MySQL
